package com.xjk.file;

import com.alibaba.fastjson.JSON;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Spliterators;
import java.util.stream.Collectors;
import javafx.util.Pair;
import javax.imageio.ImageIO;
import org.apache.commons.codec.binary.Base64;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.rendering.PDFRenderer;

public class ImageAndPdfToBase64Processor {

  /**
   * 处理目录下所有的符合条件的文件，并将它们转换为Base64编码字符串列表，默认如果是pdf将会拆分到每一页
   *
   * @param directoryPath
   * @return
   * @throws IOException
   */
  public static List<FileBase64> processFiles(String directoryPath) throws IOException {
    return processFiles(directoryPath, false);
  }

  private static boolean isURL(String path){
    try {
      URL url = new URL(path);
      String protocol = url.getProtocol();
      return protocol.equals("http") || protocol.equals("https");
    } catch (MalformedURLException e) {
      return false;
    }
  }

  public static String processFile(String urlPath) throws IOException {

    if(isURL(urlPath)){
      URL url = new URL(urlPath);
      if (isPDFUrl(urlPath)){
        return processPdfLastPage(url.openStream());
      }else {
        return processImage(url.openStream(),imageTypeFromUrl(urlPath));
      }
    }else{
      File file = new File(urlPath);
      if (file.exists()) {
        if (file.getName().toLowerCase().endsWith(".pdf")) {
          return processPdf(file);
        } else {
          return processImage(file);
        }
      }
    }
    return null;
  }

  private static File downloadFileFromUrl(String urlString, String destinationDir) throws IOException {
    URL url = new URL(urlString);
    // 创建输入流从 URL 读取数据
    try (InputStream inputStream = url.openStream()) {
      // 确定文件名
      String fileName = new File(url.getPath()).getName();
      // 创建本地文件对象
      File destinationFile = new File(destinationDir, fileName);
      // 确保目标目录存在
      if (!destinationFile.getParentFile().exists()) {
        destinationFile.getParentFile().mkdirs();
      }
      // 写入本地文件
      Files.copy(inputStream, destinationFile.toPath());
      return destinationFile;
    }
  }

  public static boolean isPDFUrl(String urlString) {
    try {
      URL url = new URL(urlString);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("HEAD");
      String contentType = connection.getContentType();
      return "application/pdf".equalsIgnoreCase(contentType);
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
  }

  /**
   * 处理目录下所有的符合条件的文件，并将它们转换为Base64编码字符串列表
   *
   * @param directoryPath
   * @param openPdfMerge  是否开启pdf拆分
   * @return
   * @throws IOException
   */
  public static List<FileBase64> processFiles(String directoryPath, boolean openPdfMerge) throws IOException {
    // 初始化一个用来存储Base64编码字符串的列表
    List<FileBase64> base64EncodedImages = new ArrayList<>();
    // 使用给定的目录路径创建一个File对象
    File directory = new File(directoryPath);
    // 列出目录下所有的文件和文件夹
    File[] files = directory.listFiles();

    // 如果目录为空，则直接返回空列表
    if (files == null) {
      return base64EncodedImages;
    }

    // 遍历目录中的每个文件
    for (File file : files) {

      if (file.isFile()) {
        String fileName = file.getName().toLowerCase();
        String fileType = getFileExtension(file);
        if (fileName.endsWith(".png") || fileName.endsWith(".jpg")) {
          String base64EncodedImage = processImage(file);
          if (base64EncodedImage != null) {
            base64EncodedImages.add(new FileBase64(fileType, 1, base64EncodedImage, fileName));
          }
        } else if (fileName.endsWith(".pdf")) {
          if (openPdfMerge) {
            String pdf = processPdf(file);
            base64EncodedImages.add(new FileBase64(fileType, 1, pdf, fileName));
          } else {
            List<Pair<Integer, String>> pdfPages = processPdfForPage(file);
            List<FileBase64> pdfPageList = pdfPages.stream().map(i -> new FileBase64(fileType, i.getKey(), i.getValue(), fileName))
                .collect(Collectors.toList());
            base64EncodedImages.addAll(pdfPageList);
          }
        }
      }
    }

    // 返回Base64编码字符串列表
    return base64EncodedImages;
  }

  /**
   * 根据文件类型（PDF或图像）处理单个文件并返回Base64编码字符串
   *
   * @param file
   * @return
   * @throws IOException
   */
  private static String processFile(File file) throws IOException {
    // 判断文件类型并调用相应的处理方法
    if (file.getName().toLowerCase().endsWith(".pdf")) {
      return processPdf(file);
    } else {
      return processImage(file);
    }
  }

  /**
   * 处理图像文件并返回Base64编码字符串
   *
   * @param file
   * @return
   * @throws IOException
   */
  private static String processImage(File file) throws IOException {

    // 读取图像文件
    BufferedImage image = ImageIO.read(file);
    // 如果无法读取图像，则返回null
    if (image == null) {
      return null;
    }

    // 将图像写入字节数组输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, getFileExtension(file), baos);
    byte[] imageBytes = baos.toByteArray();

    // 返回图像的Base64编码字符串
    return Base64.encodeBase64String(imageBytes);
  }

  private static String imageTypeFromUrl(String urlString) {
    List<String> supportedFormats = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp");

    try {
      URL url = new URL(urlString);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("HEAD");
      String contentType = connection.getContentType();

      // 检查Content-Type
      if (contentType != null && contentType.startsWith("image/")) {
        String fileType = contentType.substring(6);
        if (supportedFormats.contains(fileType)) {
          return fileType;
        }
      }

      // 如果Content-Type不确定，通过URL后缀判断
      String lowerUrl = urlString.toLowerCase();
      for (String format : supportedFormats) {
        if (lowerUrl.endsWith("." + format)) {
          return format;
        }
      }

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static String processImage(InputStream fileInputStream,String fileType) throws IOException {

    // 读取图像文件
    BufferedImage image = ImageIO.read(fileInputStream);
    // 如果无法读取图像，则返回null
    if (image == null) {
      return null;
    }

    // 将图像写入字节数组输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, fileType, baos);
    byte[] imageBytes = baos.toByteArray();

    // 返回图像的Base64编码字符串
    return Base64.encodeBase64String(imageBytes);
  }


  public static String processImage(BufferedImage image,String fileType) throws IOException {

    // 如果无法读取图像，则返回null
    if (image == null) {
      return null;
    }

    // 将图像写入字节数组输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, fileType, baos);
    byte[] imageBytes = baos.toByteArray();

    // 返回图像的Base64编码字符串
    return Base64.encodeBase64String(imageBytes);
  }


  /**
   * 处理PDF文件并返回Base64编码字符串
   *
   * @param file
   * @return
   * @throws IOException
   */
  private static String processPdf(File file) throws IOException {
    // 加载PDF文档
    PDDocument document = PDDocument.load(file);
    // 创建PDF渲染器
    PDFRenderer pdfRenderer = new PDFRenderer(document);
    // 以300DPI渲染PDF的第一页为图像
    BufferedImage image = pdfRenderer.renderImageWithDPI(0, 300);
    // 关闭PDF文档
    document.close();

    // 将图像写入字节数组输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, "png", baos);
    byte[] imageBytes = baos.toByteArray();

    // 返回图像的Base64编码字符串
    return Base64.encodeBase64String(imageBytes);
  }

  private static String processPdfLastPage(InputStream fileInputStream) throws IOException {
    // 加载PDF文档
    PDDocument document = PDDocument.load(fileInputStream);
    int numberOfPages = document.getNumberOfPages();

    // 创建PDF渲染器
    PDFRenderer pdfRenderer = new PDFRenderer(document);
    // 以300DPI渲染PDF的第一页为图像
    BufferedImage image = pdfRenderer.renderImageWithDPI(numberOfPages-1, 300);
    // 关闭PDF文档
    document.close();

    // 将图像写入字节数组输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(image, "png", baos);
    byte[] imageBytes = baos.toByteArray();

    // 返回图像的Base64编码字符串
    return Base64.encodeBase64String(imageBytes);
  }

  /**
   * 处理PDF文件并返回包含每页的Base64编码字符串及其页码的列表
   *
   * @param file
   * @return
   * @throws IOException
   */
  private static List<Pair<Integer, String>> processPdfForPage(File file) throws IOException {
    // 加载PDF文档
    PDDocument document = PDDocument.load(file);

    // 创建PDF渲染器
    PDFRenderer pdfRenderer = new PDFRenderer(document);

    // 存储每页的Base64编码字符串及页码的列表
    List<Pair<Integer, String>> pages = new ArrayList<>();

    // 遍历PDF的所有页面
    for (int page = 0; page < document.getNumberOfPages(); page++) {
      // 以300DPI渲染PDF页面为图像
      BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300);

      // 获取图像的宽度和高度
      int width = image.getWidth();
      int height = image.getHeight();

      // 检查图像尺寸是否符合要求
      if (Math.min(width, height) < 15 || Math.max(width, height) > 8192) {
        continue; // 如果不符合要求，则跳过当前页面
      }

      // 将图像写入字节数组输出流
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ImageIO.write(image, "png", baos);
      byte[] imageBytes = baos.toByteArray();

      // 将页码和图像的Base64编码字符串存入列表
      pages.add(new Pair<>(page + 1, Base64.encodeBase64String(imageBytes)));
    }

    // 关闭PDF文档
    document.close();

    // 返回包含每页的Base64编码字符串及其页码的列表
    return pages;
  }

  /**
   * 获取文件的扩展名
   *
   * @param file
   * @return
   */
  private static String getFileExtension(File file) {
    String name = file.getName();
    int lastIndexOf = name.lastIndexOf(".");
    // 如果找不到扩展名，则返回空字符串
    if (lastIndexOf == -1) {
      return ""; // 空扩展名
    }
    // 返回文件的扩展名
    return name.substring(lastIndexOf + 1);
  }

  public static void main(String[] args) {
    try {
//      List<FileBase64> base64EncodedImages = processFiles("D:\\TTT");
//      for (FileBase64 base64EncodedImage : base64EncodedImages) {
//        System.out.println(base64EncodedImage.getBase64());
//      }


      File file = new File("D:\\Desktop\\b.txt");
      File file2= new File("D:\\Desktop\\酷动FKSQ2024101785937.pdf");
      String path = file2.getPath();
      Path p = Paths.get(path);
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      PrintStream printStream = new PrintStream(fileOutputStream);
      System.setOut(printStream);

      String s =convertPDFToBase64(p);
      System.out.println(s);
      printStream.close();
      fileOutputStream.close();

    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static String convertPDFToBase64(Path pdfPath) throws IOException {
    try (PDDocument document = PDDocument.load(pdfPath.toFile())) {
      // 使用ByteArrayOutputStream来获取PDF的字节内容
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      document.save(outputStream);
      byte[] pdfBytes = outputStream.toByteArray();

      // 将字节转换为Base64字符串
      return Base64.encodeBase64String(pdfBytes);
    }
  }
}